package com.seashop.redis;

import com.alibaba.fastjson.JSON;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.RedisScript;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author moredln
 * @desc Redis抽象工具类
 * @date 11/21/20 10:55 PM
 */
public abstract class AbstractRedis {

    private RedisTemplate<String, Object> redisTemplate;

    protected AbstractRedis(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }


    /**
     * 设置缓存键值对
     *
     * @param key
     * @param value
     */
    public void set(String key, Object value) {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(key, value);
    }

    /**
     * 超时设置
     *
     * @param key      键
     * @param value    值
     * @param time     时间值
     * @param timeUnit 时间单位
     */
    public void setex(String key, Object value, long time, TimeUnit timeUnit) {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(key, value, time, timeUnit);
    }

    /**
     * 超时设置（设置时检查键）
     *
     * @param key      键
     * @param value    值
     * @param time     时间值
     * @param timeUnit 时间单位
     */
    public boolean setnx(String key, Object value, long time, TimeUnit timeUnit) {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        return opsForValue.setIfAbsent(key, value, time, timeUnit);
    }

    /**
     * 根据键拿缓存值
     *
     * @param key
     * @return
     */
    public Object get(String key) {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        return opsForValue.get(key);
    }

    /**
     * @param key  key
     * @param type 返回值类型
     */
    public <T> T get(String key, Class<T> type) {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        // Check null
        if (null == opsForValue.get(key)) {
            return null;
        }
        return JSON.parseObject(opsForValue.get(key).toString(), type);
    }

    /**
     * 批量设置
     */
    public void multiSet(Map<String, Object> map) {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        opsForValue.multiSet(map);
    }

    /**
     * 批量获取
     */
    public List<Object> multiGet(Collection<String> keys) {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        return opsForValue.multiGet(keys);
    }

    /**
     * 设置 hash
     *
     * @param h  hash
     * @param hk hash key
     * @param hv hash value
     */
    public void putHash(String h, Object hk, Object hv) {
        redisTemplate.opsForHash().put(h, hk, hv);
    }

    /**
     * 获取 hash
     *
     * @param h  hash
     * @param hk hash key
     * @return
     */
    public Object getHash(String h, Object hk) {
        return redisTemplate.opsForHash().get(h, hk);
    }

    /**
     * 指定类型获取 hash
     *
     * @param h    hash
     * @param hk   hash key
     * @param type 类型
     */
    public <T> T getHash(String h, Object hk, Class<T> type) {
        HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
        // Check null
        if (null == opsForHash.get(h, hk)) {
            return null;
        }
        return JSON.parseObject(opsForHash.get(h, hk).toString(), type);
    }

    /**
     * 获取 hash 的 keys
     *
     * @param h hash
     */
    public Set<Object> keys(String h) {
        return redisTemplate.opsForHash().keys(h);
    }

    /**
     * 获取 hash 的大小
     *
     * @param h hash
     */
    public Long size(String h) {
        return redisTemplate.opsForHash().size(h);
    }

    /**
     * 获取 hash 所有的值
     *
     * @param h hash
     */
    public List<Object> values(String h) {
        return redisTemplate.opsForHash().values(h);
    }

    /**
     * 获取 hash 里所有的键值对
     *
     * @param h hash
     */
    public Map<Object, Object> entries(String h) {
        return redisTemplate.opsForHash().entries(h);
    }

    /**
     * 批量获取 hash 里的值
     *
     * @param h        hash
     * @param hashKeys 键集合
     */
    public List<Object> multiGetHash(String h, Collection<Object> hashKeys) {
        return redisTemplate.opsForHash().multiGet(h, hashKeys);
    }

    /**
     * 检查 key 是否存在
     *
     * @param key
     * @return
     */
    public boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 自增
     *
     * @param key
     * @return
     */
    public long increment(String key) {
        ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
        return opsForValue.increment(key, 1);
    }

    /**
     * 单个删除
     *
     * @param key
     * @return
     */
    public Boolean delete(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 批量删除
     *
     * @param keys
     * @return
     */
    public Long delete(Collection<String> keys) {
        return redisTemplate.delete(keys);
    }

    public Long exec(RedisScript<Long> redisScript, List<String> lockKey, String requestId, int expireTime) {
        Long execute = redisTemplate.execute(redisScript, lockKey, requestId, expireTime);
        return execute;
    }

    public Long exec(RedisScript<Long> redisScript, List<String> lockKey, String requestId) {
        Long execute = redisTemplate.execute(redisScript, lockKey, requestId);
        return execute;
    }

}
